import { useState, forwardRef, useImperativeHandle, useRef, useEffect } from 'react';
import { Button, Drawer, Modal, message } from 'antd';
import { CloseOutlined } from '@ant-design/icons';
import _ from 'lodash';
import { uuid } from '@inbiz/utils';
import GlobalSettings from './GlobalSettings';
import Event from './Event';
import SequenceFlow from './SequenceFlow';
import FirstTask from './FirstTask';
import UserTask from './UserTask';
import Branch from './Branch';
import SubProcess from './SubProcess';
import CountersignTask from './CountersignTask';
// import ExternalTasksBase from './ExternalTasksBase';
import eventStart from '../../assets/images/eventStart.svg';
import eventEnd from '../../assets/images/eventEnd.svg';
import sequenceFlow from '../../assets/images/sequenceFlow.svg';
import taskUser from '../../assets/images/taskUser.svg';
import taskCountersign from '../../assets/images/taskCountersign.svg';
// import taskExternal from '../../assets/images/taskExternal.svg';
import branckSerial from '../../assets/images/branckSerial.svg';
import branchParallel from '../../assets/images/branchParallel.svg';
import branchInclude from '../../assets/images/branchInclude.svg';
import processSub from '../../assets/images/processSub.svg';
import {
  firstTaskId,
  getJumpRuleValue,
  setJumpRuleValue,
  setUserTaskBusinessObject,
  setUserTaskXmlCollectionProps,
  setCtSignTaskXmlCollectionProps,
  setProLconObjectToString,
  defaultUserTask,
  defaultSequenceFlowData,
  defaultProcessDefinition,
  getConditionExpressionText,
  getInitUserTask,
} from '../utils';
import './style.less';

interface customPropertiesPanelProps {
  initCurElement: any;
  customModeler: any;
  processData: any;
  propertiesPanelVisiable: boolean;
  setPropertiesPanelVisiable: any;
  defaultValue: any;
}

const CustomPropertiesPanel = forwardRef((props: customPropertiesPanelProps, ref) => {
  const { initCurElement, customModeler, processData, setPropertiesPanelVisiable, propertiesPanelVisiable, defaultValue } = props;
  const [curElement, setCurElement] = useState(initCurElement);
  const [processDefinition, setProcessDefinition] = useState(
    defaultValue?.processDefinition ? {
      ...defaultValue?.processDefinition,
      processName: processData?.name || '',
      jumpRule: getJumpRuleValue(defaultValue?.processDefinition),
      abstract: defaultValue?.processDefinition?.abstract || [],
      isReturnToDesignator: defaultValue?.processDefinition?.isReturnToDesignator || false,
      proLcon: processData?.proLcon || 'v6_font_family icon-process-morentubiao #fc9637',
      groupId: processData?.groupId || '',
    } : defaultProcessDefinition(processData));
  const [userTaskData, setUserTaskData] = useState(getInitUserTask(processData) || defaultUserTask);
  const [sequenceFlowData, setSequenceFlowData] = useState<any[]>(defaultValue?.sequenceFlow || defaultSequenceFlowData);
  const [subProcessData, setSubProcessData] = useState<any[]>(defaultValue?.callActivityTask || []);
  const processDefinitionRef = useRef<any>();
  const firstTaskRef = useRef<any>();
  const userTaskRef = useRef<any>();
  const ctSignTaskRef = useRef<any>();
  const sequenceFlowRef = useRef<any>();
  const eventRef = useRef<any>();
  const branchRef = useRef<any>();
  const subProcessRef = useRef<any>();

  const getTitleText = () => {
    const type = curElement?.type;
    const id = curElement?.id;
    if (!curElement) {
      return '全局设置';
    } else if (type == 'bpmn:StartEvent') {
      return <><img src={eventStart} />开始</>;
    } else if (type == 'bpmn:EndEvent') {
      return <><img src={eventEnd} />结束</>
    } else if (type == 'bpmn:SequenceFlow') {
      return <><img src={sequenceFlow} />流程线</>
    } else if (type == 'bpmn:CallActivity') {
      return <><img src={processSub} />子流程</>
    } else if (type == 'bpmn:ExclusiveGateway') {
      return <><img src={branckSerial} />串行分支</>
    } else if (type == 'bpmn:ParallelGateway') {
      return <><img src={branchParallel} />并行分支</>
    } else if (type == 'bpmn:InclusiveGateway') {
      return <><img src={branchInclude} />包含分支</>
    } else if (id?.startsWith('task')) {
      return <><img src={taskUser} />用户任务</>
    } else if (id?.startsWith('ctSign')) {
      return <><img src={taskCountersign} />会签任务</>
    } else {
      return ''
    }
  };

  const _component = () => {
    if (!curElement) {
      return <GlobalSettings ref={processDefinitionRef} customModeler={customModeler} processDefinition={processDefinition} processData={processData} />;
    };
    const type = curElement?.type || '';
    const id = curElement?.id || '';
    switch (type) {
      case 'bpmn:StartEvent':
      case 'bpmn:EndEvent':
        return <Event ref={eventRef} curElement={curElement} />;
      case 'bpmn:SequenceFlow':
        return <SequenceFlow ref={sequenceFlowRef} curElement={curElement} sequenceFlowData={sequenceFlowData} processData={processData} />;
      case 'bpmn:UserTask':
        if (id == firstTaskId) {
          return <FirstTask ref={firstTaskRef} curElement={curElement} userTaskData={userTaskData} processData={processData} />;
        } else if (id?.startsWith('task')) {
          return <UserTask ref={userTaskRef} curElement={curElement} userTaskData={userTaskData} processData={processData} />;
        } else if (id?.startsWith('ctSign')) {
          return <CountersignTask ref={ctSignTaskRef} curElement={curElement} userTaskData={userTaskData} processData={processData} />;
        };
      case 'bpmn:InclusiveGateway':
      case 'bpmn:ParallelGateway':
      case 'bpmn:ExclusiveGateway':
        return <Branch ref={branchRef} curElement={curElement} />;
      case 'bpmn:CallActivity':
        return <SubProcess ref={subProcessRef} curElement={curElement} subProcessData={subProcessData} processData={processData} />;
      // case 'bpmn:BusinessRuleTask':
      //   return <ExternalTasksBase curElement={curElement}/>;
      default:
        return null;
    };
  };

  const onClose = () => {
    setPropertiesPanelVisiable(false);
    let _selectedElements = customModeler.get('selection')._selectedElements;
    _selectedElements.forEach((item: any) => {
      customModeler.get('selection').deselect(item);
    });
  };

  const onSave = async () => {
    const Modeling = customModeler?.get('modeling');
    const Moddle = customModeler?.get('moddle');
    const type = curElement?.type;
    const id = curElement?.id;
    if (!curElement) {
      // 全局设置
      let data: any = {};
      try {
        data = await processDefinitionRef?.current.form.validateFields();
      } catch (error) {
        return;
      };
      const _processDefinition = {
        ...data,
        pushReachMsg: true,
        tanTemplate: data?.reachMsg?.template || null,
        pushCandidateMsg: true,
        tCandidateTemplate: data?.candidateMsg?.template || null,
        pushAssignMsg: true,
        tAssignTemplate: data?.assignMsg?.template || null,
        pushReturnMsg: true,
        trnTemplate: data?.returnMsg?.template || null,
        pushTimeOutMsg: true,
        ttonTemplate: data?.timeOutMsg?.template || null,
        pushEndMsg: true,
        pcnTemplate: data?.endMsg?.template || null,
        pushUrgingMsg: true,
        reminderMailTemplate: data?.urgingMsg?.template || null,
        isPushCancelMsg: true,
        tCancelProcessTemplate: data?.cancelMsg?.template || null,
        samePrevStartActSkip: setJumpRuleValue(data?.jumpRule, 'samePrevStartActSkip'),
        samePrevActSkip: setJumpRuleValue(data?.jumpRule, 'samePrevActSkip'),
        samePrevAllActSkip: setJumpRuleValue(data?.jumpRule, 'samePrevAllActSkip'),
        batchApproval: setJumpRuleValue(data?.jumpRule, 'batchApproval'),
        proLcon: data?.proLcon ? setProLconObjectToString(data?.proLcon) : 'v6_font_family icon-process-morentubiao #fc9637',
      };
      delete _processDefinition?.reachMsg;
      delete _processDefinition?.candidateMsg;
      delete _processDefinition?.assignMsg;
      delete _processDefinition?.returnMsg;
      delete _processDefinition?.timeOutMsg;
      delete _processDefinition?.endMsg;
      delete _processDefinition?.urgingMsg;
      delete _processDefinition?.cancelMsg;
      delete _processDefinition?.jumpRule;
      setProcessDefinition(_processDefinition);
      customModeler.processData = {
        ...customModeler.processData,
        processDefinition: _processDefinition,
      };
    };
    if (type == 'bpmn:UserTask') {
      if (id == firstTaskId) {
        // 发起人
        let data: any = {};
        try {
          data = await firstTaskRef?.current.form.validateFields();
        } catch (error) {
          return;
        };
        let _userTaskData = [...userTaskData];
        _userTaskData = _userTaskData?.map((item) => {
          if (item?.activityId == firstTaskId) {
            return data;
          } else {
            return item;
          }
        });
        setUserTaskData(_userTaskData);
        customModeler.processData = {
          ...customModeler.processData,
          userTask: _userTaskData,
        };
        Modeling.updateProperties(curElement, {
          name: data?.baseInfo?.taskName,
        });
      } else if (id?.startsWith('task')) {
        // 用户任务
        let data: any = {};
        try {
          data = await userTaskRef?.current.form.validateFields();
        } catch (error) {
          return;
        };
        let _userTaskData = [...userTaskData];
        data = {
          ...data,
          buttonSetting: {
            ...data?.buttonSetting,
            isReturnStarter: data?.buttonSetting?.restart?.includes('isReturnStarter'),
            isCdirectBack: data?.buttonSetting?.restart?.includes('isCdirectBack'),
          },
          senior: {
            ...data?.senior,
            automaticUrge: data?.senior?.automaticUrge ? true : false,
            samePrevStartActSkip: setJumpRuleValue(data?.senior?.jumpRule, 'samePrevStartActSkip'),
            samePrevActSkip: setJumpRuleValue(data?.senior?.jumpRule, 'samePrevActSkip'),
            samePrevAllActSkip: setJumpRuleValue(data?.senior?.jumpRule, 'samePrevAllActSkip'),
          },
        };
        delete data?.buttonSetting?.restart;
        delete data?.senior?.jumpRule;
        _userTaskData = _userTaskData?.map((item) => {
          if (item?.activityId == curElement?.id) {
            return data;
          } else {
            return item;
          };
        });
        setUserTaskData(_userTaskData);
        customModeler.processData = {
          ...customModeler.processData,
          userTask: _userTaskData,
        };
        const _performerType = data?.baseInfo?.performerType;
        const _performerCategory = data?.baseInfo?.performerCategory;
        const _businessObject: any = setUserTaskBusinessObject(data?.baseInfo);
        if (_performerType != '${initiator}' && _performerType != 'user' && _performerCategory == 'assigeenCategory') {
          const _collection = setUserTaskXmlCollectionProps(data?.baseInfo);
          const loopCharacteristics = Moddle.create('bpmn:MultiInstanceLoopCharacteristics', {
            isSequential: 'false',
            'activiti:elementVariable': 'assignee',
            'activiti:collection': _collection,
          });
          let _completionConditionBody = '${scriptServiceImpl.completeCondition(execution)}';
          const completionCondition = Moddle.create('bpmn:FormalExpression', { body: _completionConditionBody });
          loopCharacteristics.completionCondition = completionCondition;
          _businessObject['loopCharacteristics'] = loopCharacteristics;
        } else {
          _businessObject['loopCharacteristics'] = null;
        };
        Modeling.updateProperties(curElement, _businessObject);
      } else if (id?.startsWith('ctSign')) {
        // 会签任务
        let data: any = {};
        try {
          data = await ctSignTaskRef?.current.form.validateFields();
        } catch (error) {
          return;
        };
        let _userTaskData = [...userTaskData];
        data = {
          ...data,
          buttonSetting: {
            ...data?.buttonSetting,
            isReturnStarter: data?.buttonSetting?.restart?.includes('isReturnStarter'),
            isCdirectBack: data?.buttonSetting?.restart?.includes('isCdirectBack'),
          },
          senior: {
            ...data?.senior,
            automaticUrge: data?.senior?.automaticUrge ? true : false,
            samePrevStartActSkip: setJumpRuleValue(data?.senior?.jumpRule, 'samePrevStartActSkip'),
            samePrevActSkip: setJumpRuleValue(data?.senior?.jumpRule, 'samePrevActSkip'),
            samePrevAllActSkip: setJumpRuleValue(data?.senior?.jumpRule, 'samePrevAllActSkip'),
          },
        }
        delete data?.buttonSetting?.restart;
        _userTaskData = _userTaskData?.map((item) => {
          if (item?.activityId == curElement?.id) {
            return data;
          } else {
            return item;
          }
        });
        setUserTaskData(_userTaskData);
        customModeler.processData = {
          ...customModeler.processData,
          userTask: _userTaskData,
        };
        const _isSequential = data?.baseInfo?.isSequential ?? false;
        const _businessObject: any = {
          name: data?.baseInfo?.taskName,
          'activiti:assignee': '${assignee}',
        };
        let _collection = setCtSignTaskXmlCollectionProps(data?.baseInfo);
        const loopCharacteristics = Moddle.create('bpmn:MultiInstanceLoopCharacteristics', {
          isSequential: '' + _isSequential,
          'activiti:elementVariable': 'assignee',
          'activiti:collection': _collection,
        });
        let _completionConditionBody = '${scriptServiceImpl.completeCondition(execution)}';
        const completionCondition = Moddle.create('bpmn:FormalExpression', { body: _completionConditionBody })
        loopCharacteristics.completionCondition = completionCondition;
        _businessObject['loopCharacteristics'] = loopCharacteristics;
        Modeling.updateProperties(curElement, _businessObject);
      }
    } else if (type == 'bpmn:SequenceFlow') {
      // 连接线
      let data: any = {};
      try {
        data = await sequenceFlowRef?.current?.form?.validateFields();
      } catch (error) {
        return;
      };
      let _sequenceFlowData = [...sequenceFlowData];
      // 表达式校验
      const _conditionExpression = data?.conditionExpression || [];
      if (_conditionExpression?.length > 0) {
        for (let i = 0; i < _conditionExpression.length; i++) {
          const element = _conditionExpression[i];
          const next = _conditionExpression[i + 1];
          if (!element?.varName) {
            Modal.warning({
              title: '提示',
              content: `第${i + 1}行为空`,
            });
            return;
          };
          if (
            !element?.symbolicLogic ||
            !element?.compareValue ||
            element?.leftBracket && !element?.rightBracket ||
            element?.rightBracket && !element?.leftBracket ||
            element?.logic && (!next?.id && !next?.varName)
          ) {
            Modal.warning({
              title: '请检查表达式',
              content: getConditionExpressionText(_conditionExpression),
            });
            return;
          };
        }
      };
      _sequenceFlowData = _sequenceFlowData?.map((item) => {
        if (item?.activityId == curElement?.id) {
          return data;
        } else {
          return item;
        };
      });
      setSequenceFlowData(_sequenceFlowData);
      customModeler.processData = {
        ...customModeler.processData,
        sequenceFlow: _sequenceFlowData,
      };
      let _businessObject: any = { name: data?.remark };
      const businessObject = curElement.businessObject;
      if (_conditionExpression?.length > 0) {
        let _condition = '';
        for (let i = 0; i < _conditionExpression.length; i++) {
          const element = _conditionExpression[i];
          _condition += `${element?.leftBracket}${element?.varName}${element?.symbolicLogic}${element?.compareValue}${element?.rightBracket}${element?.logic}`;
        }
        _condition = '<![CDATA[${ ' + _condition + ' }]]>';
        const conditionExpression = Moddle.create('bpmn:FormalExpression', { body: _condition });
        businessObject.conditionExpression = conditionExpression;
        _businessObject['conditionExpression'] = conditionExpression;
      } else {
        _businessObject['conditionExpression'] = null;
      };
      Modeling.updateProperties(curElement, _businessObject);
    } else if (type == 'bpmn:StartEvent' || type == 'bpmn:EndEvent') {
      // 事件
      let data: any = {};
      try {
        data = await eventRef?.current?.form?.validateFields();
      } catch (error) {
        return;
      };
      Modeling.updateProperties(curElement, data);
    } else if (type == 'bpmn:InclusiveGateway' || type == 'bpmn:ParallelGateway' || type == 'bpmn:ExclusiveGateway') {
      // 分支
      let data: any = {};
      try {
        data = await branchRef?.current?.form?.validateFields();
      } catch (error) {
        return;
      };
      Modeling.updateProperties(curElement, data);
    } else if (type == 'bpmn:CallActivity') {
      // 子流程
      let data: any = {};
      try {
        data = await subProcessRef?.current.form.validateFields();
      } catch (error) {
        return;
      };
      // 交换变量校验
      const _psVariables = data?.psVariables;
      if (_psVariables && _psVariables?.length > 0) {
        for (let i = 0; i < _psVariables.length; i++) {
          const element = _psVariables[i];
          if (!element?.pin) {
            message.warning(`第${i + 1}行情选择父流程输入变量`);
            return;
          };
          if (!element?.pout) {
            message.warning(`第${i + 1}行情选择子流程接收变量`);
            return;
          };
          if (!element?.sout) {
            message.warning(`第${i + 1}行情选择父流程接收变量`);
            return;
          };
        }
      };
      data['callActivitiID'] = data?.callActiviti?.id || '';
      const _subProcessData = subProcessData?.map((item) => {
        if (item?.activityId == curElement?.id) {
          return data;
        } else {
          return item;
        };
      });
      setSubProcessData(_subProcessData);
      customModeler.processData = {
        ...customModeler.processData,
        callActivityTask: _subProcessData,
      };
      const _businessObject: any = {
        name: data?.activityName,
      };
      if (data?.callActivitiID) {
        _businessObject['calledElement'] = data?.callActivitiID;
      };
      if (data?.psVariables?.length) {
        const businessObject = curElement.businessObject;
        const extensionElements = Moddle.create('bpmn:ExtensionElements');
        let activitiArray: any[] = [];
        data?.psVariables?.forEach((item: { pin: string; pout: string; sout: string; }) => {
          const activitiIn = Moddle.create('activiti:In', {
            source: item?.pin,
            target: item?.pout,
          });
          activitiArray?.push(activitiIn);
          const activitiOut = Moddle.create('activiti:Out', {
            source: item?.pout,
            target: item?.sout,
          });
          activitiArray?.push(activitiOut);
        })
        extensionElements['values'] = activitiArray;
        if (!businessObject.extensionElements) {
          businessObject.extensionElements = extensionElements;
        }
        _businessObject['extensionElements'] = extensionElements;
      } else {
        _businessObject['extensionElements'] = null;
      }
      Modeling.updateProperties(curElement, _businessObject);
    };
    onClose();
  };

  useImperativeHandle(ref, () => ({
    processDefinition,
    setProcessDefinition,
    curElement,
    setCurElement,
    userTaskData,
    setUserTaskData,
    sequenceFlowData,
    setSequenceFlowData,
    subProcessData,
    setSubProcessData,
  }), [processDefinition, userTaskData, sequenceFlowData, subProcessData, curElement]);

  return (
    <Drawer
      title={getTitleText()}
      extra={<CloseOutlined onClick={onClose} />}
      closable={false}
      placement="right"
      onClose={onClose}
      visible={propertiesPanelVisiable}
      width={550}
      mask={false}
      maskClosable={false}
      destroyOnClose={true}
      className='bpmn-custom-properties-panel-wrapper'
    >
      <div className="bpmn-custom-properties-panel">
        <div className="bpmn-custom-properties-content">
          {_component()}
        </div>
        <div className="bpmn-custom-properties-panel-footer">
          <Button onClick={onClose}>取消</Button>
          <Button type='primary' onClick={onSave}>保存</Button>
        </div>
      </div>
    </Drawer>
  );
});

export default CustomPropertiesPanel;